package lider;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import com.oceanic.AsientoDTO;

import excepciones.AsientoReservadoPorOtroUsuarioException;
import excepciones.AsientoYaSobreReservadoPorElUsuarioException;
import excepciones.ErrorDeSistemaOceanicException;
import excepciones.ParametroNullException;

public class MockGestionadorOceanic extends Gestionador {
	private MockAerolineaOceanic aerolineaOceanic = new MockAerolineaOceanic();
	private double porcentaje = 0.15;
	
	
	public ArrayList<Asiento> buscarAsientosQueTengan(String origen, String destino, String fecha) {
		
		// Busca asientos con los datos no nulos origen, destino y fecha
		// Este metodo puede lanzar una excepcion ParametroNullException
		
		// lanza una excepcion en caso de que origen, destino o fecha sean null
		if ((origen == null) || (destino == null) || (fecha == null)) {
			
			if (origen == null) {
				throw new ParametroNullException("Origen");
			}
			
			if (destino == null) {
				throw new ParametroNullException("destino");
			}
			
			throw new ParametroNullException(fecha);
				
		}
		
		ArrayList<Asiento> resultadoDeBusquedaConvertido = new ArrayList<Asiento>();
		
		
			// variables -------------------------------------------------------------------------------------
		
			// obtengo la lista de asientos de la aerolinea Oceanic
			List<AsientoDTO> listaDeAsientosQueDevuelveOceanic = aerolineaOceanic.asientosDisponiblesParaOrigenYDestino(origen, destino, fecha);
			// convierto la lista de un List<AsientoDTO> a un ArrayList<Asiento>
			resultadoDeBusquedaConvertido = convertirListaAsientoDTOAListaAsiento(listaDeAsientosQueDevuelveOceanic);
		
			// codigo ---------------------------------------------------------------------------------------
	
			return resultadoDeBusquedaConvertido;
		
	}

	private ArrayList<Asiento> convertirListaAsientoDTOAListaAsiento(List<AsientoDTO> listaDeAsientosAConvertir) {
		
		// convierte una List<AsientoDTO> en ArrayList<Asiento>
		
		// variables ---------------------------------------------------------------------------------------
		ArrayList<Asiento> listaConvertida = new ArrayList<Asiento>();
		
		// codigo -----------------------------------------------------------------------------------------
		for (Iterator<AsientoDTO> iterator = listaDeAsientosAConvertir.iterator(); iterator.hasNext();) {
			AsientoDTO asientoDTO = (AsientoDTO) iterator.next();
			Asiento asientoParseado = parsearAsiento(asientoDTO);
			
			// quito el guion bajo de las ciudades en el origen y destino del asiento
			String origenSinGuionBajo = asientoParseado.getOrigen().replace("_", "");
			asientoParseado.setOrigen(origenSinGuionBajo);
			String destinoSinGuionBajo = asientoParseado.getDestino().replace("_", "");
			asientoParseado.setDestino(destinoSinGuionBajo);
			
			// seteo aerolineaOCEANIC como la aerolinea del asiento
			asientoParseado.setAerolinea(Aerolinea.aerolineaOCEANIC);
			listaConvertida.add(asientoParseado);			
		}
		
		return listaConvertida;
	}

	@Override
	public void comprarAsiento(Asiento asiento, String dni) {

		// este metodo devuelve dos excepciones, por lo que combiene tratar cada llamado con try catch para
		// AsientoReservadoPorOtroUsuarioException y ErrorDeSistemaOceanicException
		
		// variables --------------------------------------------------------------------------
				
		// intento comprar y guardo la respuesta de la interfaz de OCEANIC
		String codigoDeVuelo = asiento.getCodigoDeVuelo();
		int numeroDeAsiento = Integer.parseInt(asiento.getCodigoDeAsiento());
		boolean pudeComprar = aerolineaOceanic.comprarSiHayDisponibilidad(dni, codigoDeVuelo, numeroDeAsiento);
		boolean estaReservado = false;
		
		// codigo -----------------------------------------------------------------------------
		if (pudeComprar) {
			// si pude comprar busco si hay una lista de sobrereservas con el 
			// asiento que se compro y la remuevo del arrayList
			
			this.buscarListaSobreReservaYRemover (asiento);
			
		} else {
			
			// si no pude comprar, busco si el asiento esta reservado
			estaReservado = aerolineaOceanic.estaReservado(codigoDeVuelo, numeroDeAsiento);
			
			if (estaReservado) {
				
				// si esta reservado lanzo una excepcion AsientoReservadoPorOtroUsuarioException
				throw new AsientoReservadoPorOtroUsuarioException();
				
			} else {
				
				// si no esta reservado lanzo una excepcion ErrorDeSistemaOceanicException
				throw new ErrorDeSistemaOceanicException();
				
			}

		}
		
		
		
	}
	
	@Override
	public Asiento parsearAsiento(Object asientoParaParsear) {
		
		// variables -----------------------------------------------------------------------
		AsientoDTO asientoAParsear = (AsientoDTO) asientoParaParsear;
		Asiento asientoParseado = new Asiento(); 
		
		// codigo --------------------------------------------------------------------------- 
		
		// parseo los campos que pueden ser parseados y los demas los explisito como null
		asientoParseado.setCodigoDeVuelo(asientoAParsear.getCodigoDeVuelo());
		// como el codigo de asiento es un integer lo paso a string
		asientoParseado.setCodigoDeAsiento(Integer.toString(asientoAParsear.getNumeroDeAsiento()));
		asientoParseado.setFechaDeSalida(asientoAParsear.getFechaDeSalida());
		asientoParseado.setHoraDeSalida(asientoAParsear.getHoraDeSalida());
		// como el precio es un bigdecimal, lo parseo a string con .tostring()
		asientoParseado.setPrecio(asientoAParsear.getPrecio().toString());
		asientoParseado.setClase(asientoAParsear.getClase().substring(0, 1));
		asientoParseado.setUbicacion(asientoAParsear.getUbicacion().substring(0, 1));
		asientoParseado.setOrigen(asientoAParsear.getOrigen());
		asientoParseado.setFechaDeLlegada(asientoAParsear.getFechaDeLlegada());
		asientoParseado.setHoraDeLlegada(asientoAParsear.getHoraDeLlegada());
		asientoParseado.setDestino(asientoAParsear.getDestino());
		asientoParseado.setDNIDelQueLoReservo(null);
		asientoParseado.setReservado(false);
				
		return asientoParseado;
	}

	@Override
	public double impuestos(Asiento asiento) {
		
		// como la consigna no decia nada acerca de los impuestos de OCEANIC
		// deje este metodo igual al de LANCHITA
		double impuestos = Double.parseDouble(asiento.getPrecio());
		impuestos = impuestos * this.porcentaje;
		return impuestos;
	}

	@Override
	public void reservarAsiento(String dni, Asiento asiento) {
		
		// este metodo puede lanzar dos excepciones por lo que deberia ser tratada con un try catch
		// para AsientoYaSobreReservadoPorElUsuarioException y para ErrorDeSistemaOceanicException
		
		// variables ------------------------------------------------------------------------------
		boolean pudoReservar = false;
		// convierto el numero de asiento de string a integer
		int codigoDeAsiento = Integer.parseInt(asiento.getCodigoDeAsiento());
		String codigoDeVuelo = asiento.getCodigoDeVuelo();
		boolean yaEstaReservado = false;
		// pregunto si el asiento ya esta reservado
		yaEstaReservado = aerolineaOceanic.estaReservado(codigoDeVuelo, codigoDeAsiento);
		
		// codigo ----------------------------------------------------------------------------------
		
		if (yaEstaReservado) {
			// si ya esta reservado se sobrereserva el asiento
			
			this.sobreReservarAsiento(dni, asiento);
			
		}
		else {
			
			// si no esta reservado realiza la reserva y en caso de no poder reservar, se lanza 
			// la excepcion ErrorDeSistemaOceanicException
			pudoReservar = aerolineaOceanic.reservar(dni, codigoDeVuelo, codigoDeAsiento);
			if (!pudoReservar) {
				
				throw new ErrorDeSistemaOceanicException();

			}
		}
	}
	
	@Override
	public ArrayList<Asiento> buscarAsientosSinFecha(String origen, String destino) {
		
		// busca asientos con los datos no nulos origen y destino, y lanza
		// una excepcion ParametroNullException en caso de que alguno sea nulo

		// una excepcion ParametroNullException encaso de que origen o destino sean nulos
		if ((origen == null) || (destino == null)) {
			if (origen == null) {
				throw new ParametroNullException("origen");
			}
			throw new ParametroNullException("destino");
		}
		 
		ArrayList<Asiento> resultadoDeBusquedaConvertido = new ArrayList<Asiento>();
		
			// variables ------------------------------------------------------------------
			List<AsientoDTO> listaDeAsientosQueDevuelveOceanic = aerolineaOceanic.asientosDisponiblesParaOrigen(origen, destino); 
			// convierto la lista de un List<AsientoDTO> a un ArrayList<Asiento>
			resultadoDeBusquedaConvertido = convertirListaAsientoDTOAListaAsiento(listaDeAsientosQueDevuelveOceanic);
		
			// codigo ---------------------------------------------------------------------
		
			return resultadoDeBusquedaConvertido;
		
	}
		
}